
package br.com.aeternu.controleatendimento.exportacao;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.TreeMap;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFComment;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
import org.apache.poi.hssf.usermodel.HSSFPicture;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.IOUtils;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.data.general.DefaultPieDataset;
import br.com.aeternu.controleatendimento.common.ifc.IfcMensagemUsuario;
import br.com.aeternu.controleatendimento.common.ui.EasyOptionPane;
import br.com.aeternu.controleatendimento.excel.agenda.AgendaBean;
import br.com.aeternu.controleatendimento.excel.agenda.ExcelAgenda;
import br.com.aeternu.controleatendimento.excel.atendimento.AtendimentoBean;
import br.com.aeternu.controleatendimento.excel.atendimento.ExcelAtendimento;
import br.com.aeternu.controleatendimento.exception.ControleAtendimentoException;
import br.com.aeternu.controleatendimento.exportacao.bean.DetalheAtendimentoInternoSemanal;
import br.com.aeternu.controleatendimento.exportacao.bean.DetalheEmpresa;
import br.com.aeternu.controleatendimento.exportacao.bean.DetalheEmpresa.TipoEmpresa;
import br.com.aeternu.controleatendimento.exportacao.bean.DetalheMedicoAtendimentos;
import br.com.aeternu.controleatendimento.util.FormatUtil;

public class Exportacao
{

   private static final ResourceBundle BUNDLE = ResourceBundle
            .getBundle("br.com.aeternu.controleatendimento.resources.gui.properties.Exportacao");
   private static Logger logger = Logger.getLogger(Exportacao.class);
   private List<AgendaBean> agendaBeanList;
   private Map<String, DetalheAtendimentoInternoSemanal> detalheAtendimentoInternoMap;
   private Map<String, DetalheMedicoAtendimentos> detalheAtendimentoPorMedicoMap;
   private List<DetalheEmpresa> detalheCoordenacaoList;
   private List<DetalheEmpresa> detalheEmpresaParceiraList;
   private List<DetalheEmpresa> detalheParticularList;
   private int diasUteis;
   private Map<String, Integer> exameQtdeMap;
   private ExcelAgenda excelAgenda;
   private ExcelAtendimento excelAtendimento;
   private int maiorAgenda;
   private String periodo;
   private Map<String, Map<Date, Map<String, Map<String, List<AtendimentoBean>>>>> semanaDataTurnoMedicoAtendimentoMap;

   public Exportacao(String periodo) throws ControleAtendimentoException
   {
      this.periodo = periodo;
      this.excelAtendimento = new ExcelAtendimento();
      this.excelAgenda = new ExcelAgenda();
      this.agendaBeanList = excelAgenda.obterRegistros();

      // Mapeamentos
      this.detalheAtendimentoInternoMap = new TreeMap<String, DetalheAtendimentoInternoSemanal>();
      this.detalheAtendimentoPorMedicoMap = new TreeMap<String, DetalheMedicoAtendimentos>();
      this.exameQtdeMap = new TreeMap<String, Integer>();
      this.semanaDataTurnoMedicoAtendimentoMap = new TreeMap<String, Map<Date, Map<String, Map<String, List<AtendimentoBean>>>>>();

      // Totalizadores
      this.diasUteis = 0;
      this.maiorAgenda = 0;

      load();
   }

   public void exportarParaExcel()
   {
      DateFormat dateFormat = new SimpleDateFormat(FormatUtil.DATE_FORMAT);

      HSSFWorkbook workbook = new HSSFWorkbook();

      // idx == 5
      HSSFFont fontTitulo = workbook.createFont();
      fontTitulo.setItalic(false);
      fontTitulo.setFontHeightInPoints((short) 16);
      fontTitulo.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
      fontTitulo.setColor(new HSSFColor.RED().getIndex());

      // idx == 6
      HSSFFont fontTitulo1 = workbook.createFont();
      fontTitulo1.setItalic(false);
      fontTitulo1.setFontHeightInPoints((short) 10);
      fontTitulo1.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
      fontTitulo1.setColor(new HSSFColor.RED().getIndex());

      // idx == 7
      HSSFFont fontTituloTabela = workbook.createFont();
      fontTituloTabela.setItalic(false);
      fontTituloTabela.setFontHeightInPoints((short) 10);
      fontTituloTabela.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
      fontTituloTabela.setColor(new HSSFColor.BLUE().getIndex());

      // idx == 8
      HSSFFont fontConteudoTabela = workbook.createFont();
      fontConteudoTabela.setItalic(false);
      fontConteudoTabela.setFontHeightInPoints((short) 10);
      fontConteudoTabela.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
      fontConteudoTabela.setColor(new HSSFColor.BLACK().getIndex());

      HSSFCellStyle cellStyleTitulo = workbook.createCellStyle();
      cellStyleTitulo.setFont(workbook.getFontAt((short) 5));
      cellStyleTitulo.setAlignment(HSSFCellStyle.ALIGN_CENTER);

      HSSFCellStyle cellStyleTitulo1R = workbook.createCellStyle();
      cellStyleTitulo1R.setFont(workbook.getFontAt((short) 6));
      cellStyleTitulo1R.setAlignment(HSSFCellStyle.ALIGN_RIGHT);

      HSSFCellStyle cellStyleTitulo1L = workbook.createCellStyle();
      cellStyleTitulo1L.setFont(workbook.getFontAt((short) 6));
      cellStyleTitulo1L.setAlignment(HSSFCellStyle.ALIGN_LEFT);

      HSSFCellStyle cellStyleTitulo1C = workbook.createCellStyle();
      cellStyleTitulo1C.setFont(workbook.getFontAt((short) 6));
      cellStyleTitulo1C.setAlignment(HSSFCellStyle.ALIGN_CENTER);

      HSSFCellStyle cellStyleTituloTabela = workbook.createCellStyle();
      cellStyleTituloTabela.setFont(workbook.getFontAt((short) 7));
      cellStyleTituloTabela.setAlignment(HSSFCellStyle.ALIGN_CENTER);
      cellStyleTituloTabela.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
      cellStyleTituloTabela.setFillForegroundColor(new HSSFColor.WHITE().getIndex());
      cellStyleTituloTabela.setBorderBottom(HSSFCellStyle.BORDER_THIN);
      cellStyleTituloTabela.setBottomBorderColor(HSSFColor.BLACK.index);
      cellStyleTituloTabela.setBorderLeft(HSSFCellStyle.BORDER_THIN);
      cellStyleTituloTabela.setLeftBorderColor(HSSFColor.BLACK.index);
      cellStyleTituloTabela.setBorderRight(HSSFCellStyle.BORDER_THIN);
      cellStyleTituloTabela.setRightBorderColor(HSSFColor.BLACK.index);
      cellStyleTituloTabela.setBorderTop(HSSFCellStyle.BORDER_THIN);
      cellStyleTituloTabela.setTopBorderColor(HSSFColor.BLACK.index);

      HSSFCellStyle cellStyleConteudoTabela = workbook.createCellStyle();
      cellStyleConteudoTabela.setFont(workbook.getFontAt((short) 8));
      cellStyleConteudoTabela.setAlignment(HSSFCellStyle.ALIGN_CENTER);
      cellStyleConteudoTabela.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
      cellStyleConteudoTabela.setFillForegroundColor(new HSSFColor.WHITE().getIndex());
      cellStyleConteudoTabela.setBorderBottom(HSSFCellStyle.BORDER_THIN);
      cellStyleConteudoTabela.setBottomBorderColor(HSSFColor.BLACK.index);
      cellStyleConteudoTabela.setBorderLeft(HSSFCellStyle.BORDER_THIN);
      cellStyleConteudoTabela.setLeftBorderColor(HSSFColor.BLACK.index);
      cellStyleConteudoTabela.setBorderRight(HSSFCellStyle.BORDER_THIN);
      cellStyleConteudoTabela.setRightBorderColor(HSSFColor.BLACK.index);
      cellStyleConteudoTabela.setBorderTop(HSSFCellStyle.BORDER_THIN);
      cellStyleConteudoTabela.setTopBorderColor(HSSFColor.BLACK.index);

      HSSFCellStyle cellStyleConteudoDecimalTabela = workbook.createCellStyle();
      cellStyleConteudoDecimalTabela.setDataFormat(HSSFDataFormat.getBuiltinFormat(FormatUtil.HSSF_BUILTIN_DECIMAL));
      cellStyleConteudoDecimalTabela.setFont(workbook.getFontAt((short) 8));
      cellStyleConteudoDecimalTabela.setAlignment(HSSFCellStyle.ALIGN_CENTER);
      cellStyleConteudoDecimalTabela.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
      cellStyleConteudoDecimalTabela.setFillForegroundColor(new HSSFColor.WHITE().getIndex());
      cellStyleConteudoDecimalTabela.setBorderBottom(HSSFCellStyle.BORDER_THIN);
      cellStyleConteudoDecimalTabela.setBottomBorderColor(HSSFColor.BLACK.index);
      cellStyleConteudoDecimalTabela.setBorderLeft(HSSFCellStyle.BORDER_THIN);
      cellStyleConteudoDecimalTabela.setLeftBorderColor(HSSFColor.BLACK.index);
      cellStyleConteudoDecimalTabela.setBorderRight(HSSFCellStyle.BORDER_THIN);
      cellStyleConteudoDecimalTabela.setRightBorderColor(HSSFColor.BLACK.index);
      cellStyleConteudoDecimalTabela.setBorderTop(HSSFCellStyle.BORDER_THIN);
      cellStyleConteudoDecimalTabela.setTopBorderColor(HSSFColor.BLACK.index);

      HSSFCellStyle cellStyleConteudoPercentualTabela = workbook.createCellStyle();
      cellStyleConteudoPercentualTabela.setDataFormat(HSSFDataFormat.getBuiltinFormat(FormatUtil.HSSF_BUILTIN_PERCENT));
      cellStyleConteudoPercentualTabela.setFont(workbook.getFontAt((short) 8));
      cellStyleConteudoPercentualTabela.setAlignment(HSSFCellStyle.ALIGN_CENTER);
      cellStyleConteudoPercentualTabela.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
      cellStyleConteudoPercentualTabela.setFillForegroundColor(new HSSFColor.WHITE().getIndex());
      cellStyleConteudoPercentualTabela.setBorderBottom(HSSFCellStyle.BORDER_THIN);
      cellStyleConteudoPercentualTabela.setBottomBorderColor(HSSFColor.BLACK.index);
      cellStyleConteudoPercentualTabela.setBorderLeft(HSSFCellStyle.BORDER_THIN);
      cellStyleConteudoPercentualTabela.setLeftBorderColor(HSSFColor.BLACK.index);
      cellStyleConteudoPercentualTabela.setBorderRight(HSSFCellStyle.BORDER_THIN);
      cellStyleConteudoPercentualTabela.setRightBorderColor(HSSFColor.BLACK.index);
      cellStyleConteudoPercentualTabela.setBorderTop(HSSFCellStyle.BORDER_THIN);
      cellStyleConteudoPercentualTabela.setTopBorderColor(HSSFColor.BLACK.index);

      @SuppressWarnings("unused")
      HSSFRow rowVazia;

      for (String semana : semanaDataTurnoMedicoAtendimentoMap.keySet())
      {
         HSSFSheet sheetSemana = workbook.createSheet(semana);

         HSSFRow rowTitulo = sheetSemana.createRow(0);
         HSSFCell cellTitulo = rowTitulo.createCell(0);
         cellTitulo.setCellValue(IfcMensagemUsuario.HEADER_RELATORIO);
         cellTitulo.setCellStyle(cellStyleTitulo);

         sheetSemana.addMergedRegion(new CellRangeAddress(0, 0, 0, 7));

         rowVazia = sheetSemana.createRow(sheetSemana.getLastRowNum() + 1);

         Map<Date, Map<String, Map<String, List<AtendimentoBean>>>> dataTurnoMedicoAtendimentoMap =
            semanaDataTurnoMedicoAtendimentoMap.get(semana);
         for (Date data : dataTurnoMedicoAtendimentoMap.keySet())
         {

            Map<String, Map<String, List<AtendimentoBean>>> turnoMedicoAtendimentoMap = dataTurnoMedicoAtendimentoMap.get(data);
            for (String turno : turnoMedicoAtendimentoMap.keySet())
            {

               Map<String, List<AtendimentoBean>> medicoAtendimentoMap = turnoMedicoAtendimentoMap.get(turno);
               for (String medico : medicoAtendimentoMap.keySet())
               {
                  HSSFRow rowIdentificacao = sheetSemana.createRow(sheetSemana.getLastRowNum() + 1);

                  HSSFCell cellIdentificacaoMedico = rowIdentificacao.createCell(0);
                  cellIdentificacaoMedico.setCellValue(BUNDLE.getString("semana.titulo.medico"));
                  cellIdentificacaoMedico.setCellStyle(cellStyleTitulo1R);

                  HSSFCell cellIdentificacaoMedicoNome = rowIdentificacao.createCell((int) rowIdentificacao.getLastCellNum());
                  cellIdentificacaoMedicoNome.setCellValue(medico);
                  cellIdentificacaoMedicoNome.setCellStyle(cellStyleTitulo1L);

                  HSSFCell cellIdentificacaoData = rowIdentificacao.createCell((int) rowIdentificacao.getLastCellNum());
                  cellIdentificacaoData.setCellValue("Data:");
                  cellIdentificacaoData.setCellStyle(cellStyleTitulo1R);

                  HSSFCell cellIdentificacaoDataValor = rowIdentificacao.createCell((int) rowIdentificacao.getLastCellNum());
                  cellIdentificacaoDataValor.setCellValue(dateFormat.format(data));
                  cellIdentificacaoDataValor.setCellStyle(cellStyleTitulo1L);

                  HSSFCell cellIdentificacaoTurno = rowIdentificacao.createCell((int) rowIdentificacao.getLastCellNum());
                  cellIdentificacaoTurno.setCellValue("Turno:");
                  cellIdentificacaoTurno.setCellStyle(cellStyleTitulo1R);

                  HSSFCell cellIdentificacaoTurnoValor = rowIdentificacao.createCell((int) rowIdentificacao.getLastCellNum());
                  cellIdentificacaoTurnoValor.setCellValue(turno);
                  cellIdentificacaoTurnoValor.setCellStyle(cellStyleTitulo1L);

                  HSSFRow rowTituloDetalhe = sheetSemana.createRow(sheetSemana.getLastRowNum() + 1);

                  HSSFCell cellTituloDetalheOrdem = rowTituloDetalhe.createCell(0);
                  cellTituloDetalheOrdem.setCellValue("QTDE.");
                  cellTituloDetalheOrdem.setCellStyle(cellStyleTituloTabela);

                  HSSFCell cellTituloDetalhePaciente = rowTituloDetalhe.createCell((int) rowTituloDetalhe.getLastCellNum());
                  cellTituloDetalhePaciente.setCellValue("PACIENTE");
                  cellTituloDetalhePaciente.setCellStyle(cellStyleTituloTabela);

                  HSSFCell cellTituloDetalheTipoExame = rowTituloDetalhe.createCell((int) rowTituloDetalhe.getLastCellNum());
                  cellTituloDetalheTipoExame.setCellValue("TIPO DE EXAME");
                  cellTituloDetalheTipoExame.setCellStyle(cellStyleTituloTabela);

                  HSSFCell cellTituloDetalheCoordenacao = rowTituloDetalhe.createCell((int) rowTituloDetalhe.getLastCellNum());
                  cellTituloDetalheCoordenacao.setCellValue("COORDENAÇÃO");
                  cellTituloDetalheCoordenacao.setCellStyle(cellStyleTituloTabela);

                  HSSFCell cellTituloDetalheEmpresaParceira = rowTituloDetalhe.createCell((int) rowTituloDetalhe.getLastCellNum());
                  cellTituloDetalheEmpresaParceira.setCellValue("EMPRESA PARCEIRA");
                  cellTituloDetalheEmpresaParceira.setCellStyle(cellStyleTituloTabela);

                  HSSFCell cellTituloDetalheParticular = rowTituloDetalhe.createCell((int) rowTituloDetalhe.getLastCellNum());
                  cellTituloDetalheParticular.setCellValue("PARTICULAR");
                  cellTituloDetalheParticular.setCellStyle(cellStyleTituloTabela);

                  HSSFCell cellTituloDetalheConclusaoPendencia = rowTituloDetalhe.createCell((int) rowTituloDetalhe.getLastCellNum());
                  cellTituloDetalheConclusaoPendencia.setCellValue("CONCLUSÃO/PENDÊNCIA");
                  cellTituloDetalheConclusaoPendencia.setCellStyle(cellStyleTituloTabela);

                  HSSFCell cellTituloDetalheQtde = rowTituloDetalhe.createCell((int) rowTituloDetalhe.getLastCellNum());
                  cellTituloDetalheQtde.setCellValue("QTDE.");
                  cellTituloDetalheQtde.setCellStyle(cellStyleTituloTabela);

                  List<AtendimentoBean> atendimentoList = medicoAtendimentoMap.get(medico);
                  int ordem = 1;
                  for (AtendimentoBean bean : atendimentoList)
                  {
                     HSSFRow rowDetalhe = sheetSemana.createRow(sheetSemana.getLastRowNum() + 1);

                     HSSFCell cellDetalheOrdem = rowDetalhe.createCell(0);
                     cellDetalheOrdem.setCellValue(ordem);
                     cellDetalheOrdem.setCellStyle(cellStyleConteudoTabela);

                     HSSFCell cellDetalhePaciente = rowDetalhe.createCell(1);
                     cellDetalhePaciente.setCellValue(bean.getPaciente());
                     cellDetalhePaciente.setCellStyle(cellStyleConteudoTabela);

                     HSSFCell cellDetalheTipoExame = rowDetalhe.createCell(2);
                     cellDetalheTipoExame.setCellValue(bean.getTipoDeExame());
                     cellDetalheTipoExame.setCellStyle(cellStyleConteudoTabela);

                     HSSFCell cellDetalheCoordenacao = rowDetalhe.createCell(3);
                     cellDetalheCoordenacao.setCellValue(bean.getCoordenacao());
                     cellDetalheCoordenacao.setCellStyle(cellStyleConteudoTabela);

                     HSSFCell cellDetalheEmpresaParceira = rowDetalhe.createCell(4);
                     cellDetalheEmpresaParceira.setCellValue(bean.getEmpresaParceira());
                     cellDetalheEmpresaParceira.setCellStyle(cellStyleConteudoTabela);

                     HSSFCell cellDetalheParticular = rowDetalhe.createCell(5);
                     cellDetalheParticular.setCellValue(bean.getParticular());
                     cellDetalheParticular.setCellStyle(cellStyleConteudoTabela);

                     HSSFCell cellDetalheConclusaoPendencia = rowDetalhe.createCell(6);
                     cellDetalheConclusaoPendencia.setCellValue(bean.getConclusaoPendencia());
                     cellDetalheConclusaoPendencia.setCellStyle(cellStyleConteudoTabela);

                     HSSFCell cellDetalheQtde = rowDetalhe.createCell(7);
                     cellDetalheQtde.setCellValue(bean.getQuantidade());
                     cellDetalheQtde.setCellStyle(cellStyleConteudoTabela);

                     ordem++;
                  }

                  sheetSemana.autoSizeColumn(0);
                  sheetSemana.autoSizeColumn(1);
                  sheetSemana.autoSizeColumn(2);
                  sheetSemana.autoSizeColumn(3);
                  sheetSemana.autoSizeColumn(4);
                  sheetSemana.autoSizeColumn(5);
                  sheetSemana.autoSizeColumn(6);
                  sheetSemana.autoSizeColumn(7);

                  rowVazia = sheetSemana.createRow(sheetSemana.getLastRowNum() + 1);
               }
            }
         }
      }

      HSSFSheet sheetConsolidacao = workbook.createSheet("Consolidação");

      HSSFPatriarch patrConsolidacao = sheetConsolidacao.createDrawingPatriarch();

      HSSFRow rowTitulo = sheetConsolidacao.createRow(0);
      HSSFCell cellTitulo = rowTitulo.createCell(0);
      cellTitulo.setCellValue("ATENDIMENTOS REALIZADOS");
      sheetConsolidacao.addMergedRegion(new CellRangeAddress(0, 0, 0, 3));
      cellTitulo.setCellStyle(cellStyleTitulo1C);

      HSSFRow rowTituloTabela = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellTituloTabela = rowTituloTabela.createCell(0);
      cellTituloTabela.setCellValue("SEMANA");
      cellTituloTabela.setCellStyle(cellStyleTituloTabela);

      cellTituloTabela = rowTituloTabela.createCell(1);
      cellTituloTabela.setCellValue("ATDs");
      cellTituloTabela.setCellStyle(cellStyleTituloTabela);

      cellTituloTabela = rowTituloTabela.createCell(2);
      cellTituloTabela.setCellValue("AGENDAS");
      cellTituloTabela.setCellStyle(cellStyleTituloTabela);

      cellTituloTabela = rowTituloTabela.createCell(3);
      cellTituloTabela.setCellValue("> 25 ATDs");
      cellTituloTabela.setCellStyle(cellStyleTituloTabela);

      int totalAtendimentos = 0;
      int totalAgendas = 0;
      int totalMedicosComMaisDe25Atendimentos = 0;
      for (String semana : detalheAtendimentoInternoMap.keySet())
      {
         DetalheAtendimentoInternoSemanal detalheAtendimentoInternoSemanal = detalheAtendimentoInternoMap.get(semana);
         int medicosComMaisDe25Atendimentos =
            getQuantidadeMedicosComMaisDe25Atendimentos(detalheAtendimentoInternoSemanal.getMedicoAtendimentosMap());

         HSSFRow rowConteudoTabela = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
         HSSFCell cellConteudoTabela = rowConteudoTabela.createCell(0);
         cellConteudoTabela.setCellValue(semana);
         cellConteudoTabela.setCellStyle(cellStyleConteudoTabela);
         cellConteudoTabela = rowConteudoTabela.createCell(1);
         cellConteudoTabela.setCellValue(detalheAtendimentoInternoSemanal.getAtendimentos());
         cellConteudoTabela.setCellStyle(cellStyleConteudoTabela);
         cellConteudoTabela = rowConteudoTabela.createCell(2);
         cellConteudoTabela.setCellValue(detalheAtendimentoInternoSemanal.getAgendas());
         cellConteudoTabela.setCellStyle(cellStyleConteudoTabela);
         cellConteudoTabela = rowConteudoTabela.createCell(3);
         cellConteudoTabela.setCellValue(medicosComMaisDe25Atendimentos);
         cellConteudoTabela.setCellStyle(cellStyleConteudoTabela);

         if (medicosComMaisDe25Atendimentos > 0)
         {
            HSSFComment comment = patrConsolidacao.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short) 4, 2, (short) 8, 7));
            comment.setString(new HSSFRichTextString(getMedicosComMaisDe25Atendimentos(detalheAtendimentoInternoSemanal
                     .getMedicoAtendimentosMap())));
            cellConteudoTabela.setCellComment(comment);
         }

         totalAtendimentos += detalheAtendimentoInternoSemanal.getAtendimentos();
         totalAgendas += detalheAtendimentoInternoSemanal.getAgendas();
         totalMedicosComMaisDe25Atendimentos += medicosComMaisDe25Atendimentos;
      }

      HSSFRow rowFechamentoTabela = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellFechamentoTabela = rowFechamentoTabela.createCell(0);
      cellFechamentoTabela.setCellValue("TOTAIS");
      cellFechamentoTabela.setCellStyle(cellStyleTituloTabela);
      cellFechamentoTabela = rowFechamentoTabela.createCell(1);
      cellFechamentoTabela.setCellValue(totalAtendimentos);
      cellFechamentoTabela.setCellStyle(cellStyleTituloTabela);
      cellFechamentoTabela = rowFechamentoTabela.createCell(2);
      cellFechamentoTabela.setCellValue(totalAgendas);
      cellFechamentoTabela.setCellStyle(cellStyleTituloTabela);
      cellFechamentoTabela = rowFechamentoTabela.createCell(3);
      cellFechamentoTabela.setCellValue(totalMedicosComMaisDe25Atendimentos);
      cellFechamentoTabela.setCellStyle(cellStyleTituloTabela);

      rowVazia = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);

      // TABELA: Quantidade de agendas internas, Quantidade de agendas com mais de 25 atendimentos (com %) e Maior quantidade de
      // atendimentos realizados por um médico em um turno qualquer
      HSSFRow rowAgendasInternas = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellAgendasInternasTitulo = rowAgendasInternas.createCell(0);
      cellAgendasInternasTitulo.setCellValue("AGENDAS INTERNAS/MÊS:");
      cellAgendasInternasTitulo.setCellStyle(cellStyleTitulo1R);
      HSSFCell cellAgendasInternasConteudo = rowAgendasInternas.createCell(1);
      cellAgendasInternasConteudo.setCellValue(totalAgendas);
      cellAgendasInternasConteudo.setCellStyle(cellStyleConteudoTabela);
      HSSFRow rowAgendasComMaisDe25Atds = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellAgendasComMaisDe25AtdsTitulo = rowAgendasComMaisDe25Atds.createCell(0);
      cellAgendasComMaisDe25AtdsTitulo.setCellValue("AGENDAS ACIMA 25 ATDs:");
      cellAgendasComMaisDe25AtdsTitulo.setCellStyle(cellStyleTitulo1R);
      HSSFCell cellAgendasComMaisDe25AtdsConteudo = rowAgendasComMaisDe25Atds.createCell(1);
      cellAgendasComMaisDe25AtdsConteudo.setCellValue(totalMedicosComMaisDe25Atendimentos);
      cellAgendasComMaisDe25AtdsConteudo.setCellStyle(cellStyleConteudoTabela);
      HSSFCell cellAgendasComMaisDe25AtdsPercentual = rowAgendasComMaisDe25Atds.createCell(2);
      cellAgendasComMaisDe25AtdsPercentual.setCellValue((double) totalMedicosComMaisDe25Atendimentos / totalAgendas);
      cellAgendasComMaisDe25AtdsPercentual.setCellStyle(cellStyleConteudoPercentualTabela);
      HSSFRow rowMaiorAgenda = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellMaiorAgendaTitulo = rowMaiorAgenda.createCell(0);
      cellMaiorAgendaTitulo.setCellValue("MAIOR AGENDA:");
      cellMaiorAgendaTitulo.setCellStyle(cellStyleTitulo1R);
      HSSFCell cellMaiorAgendaConteudo = rowMaiorAgenda.createCell(1);
      cellMaiorAgendaConteudo.setCellValue(getMaiorAgenda());
      cellMaiorAgendaConteudo.setCellStyle(cellStyleConteudoTabela);

      rowVazia = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);

      // TABELA: Dias úteis, Atendimentos por Dia e Atendimentos por Período
      HSSFRow rowDiasUteis = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellDiasUteisTitulo = rowDiasUteis.createCell(0);
      cellDiasUteisTitulo.setCellValue("DIAS ÚTEIS/MÊS:");
      cellDiasUteisTitulo.setCellStyle(cellStyleTitulo1R);
      HSSFCell cellDiasUteisValor = rowDiasUteis.createCell(1);
      cellDiasUteisValor.setCellValue(diasUteis);
      cellDiasUteisValor.setCellStyle(cellStyleConteudoTabela);
      HSSFRow rowAtendimentosPorDia = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellAtendimentosPorDiaTitulo = rowAtendimentosPorDia.createCell(0);
      cellAtendimentosPorDiaTitulo.setCellValue("ATENDIMENTOS/DIA:");
      cellAtendimentosPorDiaTitulo.setCellStyle(cellStyleTitulo1R);
      HSSFCell cellAtendimentosPorDiaValor = rowAtendimentosPorDia.createCell(1);
      cellAtendimentosPorDiaValor.setCellValue((double) totalAtendimentos / diasUteis);
      cellAtendimentosPorDiaValor.setCellStyle(cellStyleConteudoDecimalTabela);
      HSSFRow rowAtendimentosPorPeriodo = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellAtendimentosPorPeriodoTitulo = rowAtendimentosPorPeriodo.createCell(0);
      cellAtendimentosPorPeriodoTitulo.setCellValue("ATENDIMENTOS/PERÍODO:");
      cellAtendimentosPorPeriodoTitulo.setCellStyle(cellStyleTitulo1R);
      HSSFCell cellAtendimentosPorPeriodoValor = rowAtendimentosPorPeriodo.createCell(1);
      cellAtendimentosPorPeriodoValor.setCellValue(((double) totalAtendimentos / diasUteis) / 2);
      cellAtendimentosPorPeriodoValor.setCellStyle(cellStyleConteudoDecimalTabela);

      rowVazia = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);

      // TABELA: Atendimentos por Médicos
      HSSFRow rowAtendimentosPorMedicosCabecalho = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellAtendimentosPorMedicosCabecalho = rowAtendimentosPorMedicosCabecalho.createCell(0);
      cellAtendimentosPorMedicosCabecalho.setCellValue("ATENDIMENTOS INTERNOS");
      cellAtendimentosPorMedicosCabecalho.setCellStyle(cellStyleTitulo1C);
      sheetConsolidacao.addMergedRegion(new CellRangeAddress(sheetConsolidacao.getLastRowNum(), sheetConsolidacao.getLastRowNum(), 0, 3));
      HSSFRow rowAtendimentosPorMedicosTitulo = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellAtendimentosPorMedicosMedicoTitulo = rowAtendimentosPorMedicosTitulo.createCell(0);
      cellAtendimentosPorMedicosMedicoTitulo.setCellValue("MÉDICO");
      cellAtendimentosPorMedicosMedicoTitulo.setCellStyle(cellStyleTituloTabela);
      HSSFCell cellAtendimentosPorMedicosAgendasTitulo = rowAtendimentosPorMedicosTitulo.createCell(1);
      cellAtendimentosPorMedicosAgendasTitulo.setCellValue("AGENDAS");
      cellAtendimentosPorMedicosAgendasTitulo.setCellStyle(cellStyleTituloTabela);
      HSSFCell cellAtendimentosPorMedicosAtendimentosTitulo = rowAtendimentosPorMedicosTitulo.createCell(2);
      cellAtendimentosPorMedicosAtendimentosTitulo.setCellValue("ATENDIMENTOS");
      cellAtendimentosPorMedicosAtendimentosTitulo.setCellStyle(cellStyleTituloTabela);
      HSSFCell cellAtendimentosPorMedicosMediaTitulo = rowAtendimentosPorMedicosTitulo.createCell(3);
      cellAtendimentosPorMedicosMediaTitulo.setCellValue("MÉDIA");
      cellAtendimentosPorMedicosMediaTitulo.setCellStyle(cellStyleTituloTabela);

      totalAgendas = 0;
      totalAtendimentos = 0;
      DefaultPieDataset pieDataset = new DefaultPieDataset();
      for (String medico : detalheAtendimentoPorMedicoMap.keySet())
      {
         DetalheMedicoAtendimentos detalheAtendimentoPorMedico = detalheAtendimentoPorMedicoMap.get(medico);

         HSSFRow rowAtendimentosPorMedicosConteudo = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
         HSSFCell cellAtendimentosPorMedicosMedicoConteudo = rowAtendimentosPorMedicosConteudo.createCell(0);
         cellAtendimentosPorMedicosMedicoConteudo.setCellValue(medico);
         cellAtendimentosPorMedicosMedicoConteudo.setCellStyle(cellStyleConteudoTabela);
         HSSFCell cellAtendimentosPorMedicosAgendasConteudo = rowAtendimentosPorMedicosConteudo.createCell(1);
         cellAtendimentosPorMedicosAgendasConteudo.setCellValue(detalheAtendimentoPorMedico.getQuantidadeAgendas());
         cellAtendimentosPorMedicosAgendasConteudo.setCellStyle(cellStyleConteudoTabela);
         HSSFCell cellAtendimentosPorMedicosAtendimentosConteudo = rowAtendimentosPorMedicosConteudo.createCell(2);
         cellAtendimentosPorMedicosAtendimentosConteudo.setCellValue(detalheAtendimentoPorMedico.getQuantidadeAtendimentos());
         cellAtendimentosPorMedicosAtendimentosConteudo.setCellStyle(cellStyleConteudoTabela);
         HSSFCell cellAtendimentosPorMedicosMediaConteudo = rowAtendimentosPorMedicosConteudo.createCell(3);
         cellAtendimentosPorMedicosMediaConteudo.setCellValue((double) detalheAtendimentoPorMedico
                  .getQuantidadeAtendimentos() / detalheAtendimentoPorMedico.getQuantidadeAgendas());
         cellAtendimentosPorMedicosMediaConteudo.setCellStyle(cellStyleConteudoDecimalTabela);

         totalAgendas += detalheAtendimentoPorMedico.getQuantidadeAgendas();
         totalAtendimentos += detalheAtendimentoPorMedico.getQuantidadeAtendimentos();

         pieDataset.setValue(medico + " (" + detalheAtendimentoPorMedico.getQuantidadeAtendimentos() + ")",
            detalheAtendimentoPorMedico.getQuantidadeAtendimentos());
      }

      JFreeChart pieChart = ChartFactory.createPieChart("ATENDIMENTOS INTERNOS", pieDataset, true, true, false);
      int width = 640;
      int height = 480;
      float quality = 1;
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      try
      {
         ChartUtilities.writeChartAsJPEG(baos, quality, pieChart, width, height);
         InputStream is = new ByteArrayInputStream(baos.toByteArray());
         byte[] bytes = IOUtils.toByteArray(is);
         int chartId = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
         ClientAnchor anchor = new HSSFClientAnchor();
         anchor.setCol1(rowAtendimentosPorMedicosTitulo.getLastCellNum());
         anchor.setRow1(rowAtendimentosPorMedicosCabecalho.getRowNum());
         HSSFPicture chartPicture = patrConsolidacao.createPicture(anchor, chartId);
         chartPicture.resize();
      }
      catch (IOException e)
      {
         logger.error("Não foi possível gerar o gráfico dos atendimentos por médicos.");
         logger.error(e.getMessage(), e);
      }

      HSSFRow rowAtendimentosPorMedicosRodape = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellAtendimentosPorMedicosTotais = rowAtendimentosPorMedicosRodape.createCell(0);
      cellAtendimentosPorMedicosTotais.setCellValue("TOTAIS");
      cellAtendimentosPorMedicosTotais.setCellStyle(cellStyleTituloTabela);
      HSSFCell cellAtendimentosPorMedicosTotalAgendas = rowAtendimentosPorMedicosRodape.createCell(1);
      cellAtendimentosPorMedicosTotalAgendas.setCellValue(totalAgendas);
      cellAtendimentosPorMedicosTotalAgendas.setCellStyle(cellStyleTituloTabela);
      HSSFCell cellAtendimentosPorMedicosTotalAtendimentos = rowAtendimentosPorMedicosRodape.createCell(2);
      cellAtendimentosPorMedicosTotalAtendimentos.setCellValue(totalAtendimentos);
      cellAtendimentosPorMedicosTotalAtendimentos.setCellStyle(cellStyleTituloTabela);

      rowVazia = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);

      // TABELA: Tipos de Exames
      HSSFRow rowTiposDeExamesCabecalho = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellTiposDeExamesCabecalho = rowTiposDeExamesCabecalho.createCell(0);
      cellTiposDeExamesCabecalho.setCellValue("TIPOS DE EXAMES REALIZADOS");
      cellTiposDeExamesCabecalho.setCellStyle(cellStyleTitulo1C);
      sheetConsolidacao.addMergedRegion(new CellRangeAddress(sheetConsolidacao.getLastRowNum(), sheetConsolidacao.getLastRowNum(), 0, 1));
      HSSFRow rowTiposDeExamesTitulo = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellTiposDeExamesNomeTitulo = rowTiposDeExamesTitulo.createCell(0);
      cellTiposDeExamesNomeTitulo.setCellValue("EXAME");
      cellTiposDeExamesNomeTitulo.setCellStyle(cellStyleTituloTabela);
      HSSFCell cellTiposDeExamesQtdeTitulo = rowTiposDeExamesTitulo.createCell(1);
      cellTiposDeExamesQtdeTitulo.setCellValue("QTDE.");
      cellTiposDeExamesQtdeTitulo.setCellStyle(cellStyleTituloTabela);

      int totalExames = 0;
      for (String tipoExame : exameQtdeMap.keySet())
      {
         int qtde = exameQtdeMap.get(tipoExame);
         HSSFRow rowTiposDeExamesNomeConteudo = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
         HSSFCell cellTiposDeExamesNomeConteudo = rowTiposDeExamesNomeConteudo.createCell(0);
         cellTiposDeExamesNomeConteudo.setCellValue(tipoExame);
         cellTiposDeExamesNomeConteudo.setCellStyle(cellStyleConteudoTabela);
         HSSFCell cellTiposDeExamesQtdeConteudo = rowTiposDeExamesNomeConteudo.createCell(1);
         cellTiposDeExamesQtdeConteudo.setCellValue(qtde);
         cellTiposDeExamesQtdeConteudo.setCellStyle(cellStyleConteudoTabela);
         totalExames += qtde;
      }

      HSSFRow rowTiposDeExamesRodape = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellTiposDeExamesTotalRodape = rowTiposDeExamesRodape.createCell(0);
      cellTiposDeExamesTotalRodape.setCellValue("TOTAL");
      cellTiposDeExamesTotalRodape.setCellStyle(cellStyleTituloTabela);
      HSSFCell cellTiposDeExamesQtdeRodape = rowTiposDeExamesRodape.createCell(1);
      cellTiposDeExamesQtdeRodape.setCellValue(totalExames);
      cellTiposDeExamesQtdeRodape.setCellStyle(cellStyleTituloTabela);

      rowVazia = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);

      HSSFRow rowEmpresasAtendidasCabecalho = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellEmpresasAtendidasCabecalho = rowEmpresasAtendidasCabecalho.createCell(0);
      cellEmpresasAtendidasCabecalho.setCellValue("EMPRESAS ATENDIDAS");
      cellEmpresasAtendidasCabecalho.setCellStyle(cellStyleTitulo1C);
      sheetConsolidacao.addMergedRegion(new CellRangeAddress(sheetConsolidacao.getLastRowNum(), sheetConsolidacao.getLastRowNum(), 0, 2));

      rowVazia = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);

      // TABELA: 10 coordenações mais atendidas
      HSSFRow rowCoordenacoesCabecalho = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellCoordenacoesCabecalho = rowCoordenacoesCabecalho.createCell(0);
      cellCoordenacoesCabecalho.setCellValue("EMPRESAS COORD./EXEC. (As 10 empresas mais atendidas)");
      cellCoordenacoesCabecalho.setCellStyle(cellStyleTitulo1C);
      sheetConsolidacao.addMergedRegion(new CellRangeAddress(sheetConsolidacao.getLastRowNum(), sheetConsolidacao.getLastRowNum(), 0, 3));
      HSSFRow rowCoordenacoesTitulo = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellCoordenacoesNomeTitulo = rowCoordenacoesTitulo.createCell(0);
      cellCoordenacoesNomeTitulo.setCellValue("COORDENAÇÃO");
      cellCoordenacoesNomeTitulo.setCellStyle(cellStyleTituloTabela);
      HSSFCell cellCoordenacoesQtdeTitulo = rowCoordenacoesTitulo.createCell(1);
      cellCoordenacoesQtdeTitulo.setCellValue("QTDE.");
      cellCoordenacoesQtdeTitulo.setCellStyle(cellStyleTituloTabela);
      HSSFCell cellCoordenacoesPercTitulo = rowCoordenacoesTitulo.createCell(2);
      cellCoordenacoesPercTitulo.setCellValue("%");
      cellCoordenacoesPercTitulo.setCellStyle(cellStyleTituloTabela);
      HSSFComment comment = patrConsolidacao.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short) 2, 0, (short) 6, 5));
      comment.setString(new HSSFRichTextString("Percentual em relação a todos os atendimentos"));
      cellCoordenacoesPercTitulo.setCellComment(comment);

      int j = (detalheCoordenacaoList.size() > 10 ? 10 : detalheCoordenacaoList.size());
      for (int i = 1; i <= j; i++)
      {
         int index = detalheCoordenacaoList.size() - i;
         DetalheEmpresa detalhe = detalheCoordenacaoList.get(index);

         HSSFRow rowCoordenacoesConteudo = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
         HSSFCell cellCoordenacoesNomeConteudo = rowCoordenacoesConteudo.createCell(0);
         cellCoordenacoesNomeConteudo.setCellValue(detalhe.getNome());
         cellCoordenacoesNomeConteudo.setCellStyle(cellStyleConteudoTabela);
         HSSFCell cellCoordenacoesQtdeConteudo = rowCoordenacoesConteudo.createCell(1);
         cellCoordenacoesQtdeConteudo.setCellValue(detalhe.getQuantidadeAtendimentos());
         cellCoordenacoesQtdeConteudo.setCellStyle(cellStyleConteudoTabela);
         HSSFCell cellCoordenacoesPercConteudo = rowCoordenacoesConteudo.createCell(2);
         cellCoordenacoesPercConteudo.setCellValue((double) detalhe.getQuantidadeAtendimentos() / totalAtendimentos);
         cellCoordenacoesPercConteudo.setCellStyle(cellStyleConteudoPercentualTabela);
      }

      rowVazia = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);

      // TABELA: Empresas Parceiras
      HSSFRow rowEmpresasParceirasCabecalho = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellEmpresasParceirasCabecalho = rowEmpresasParceirasCabecalho.createCell(0);
      cellEmpresasParceirasCabecalho.setCellValue("EMPRESAS PARCEIRAS");
      cellEmpresasParceirasCabecalho.setCellStyle(cellStyleTitulo1C);
      sheetConsolidacao.addMergedRegion(new CellRangeAddress(sheetConsolidacao.getLastRowNum(), sheetConsolidacao.getLastRowNum(), 0, 3));
      HSSFRow rowEmpresasParceirasTitulo = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellEmpresasParceirasNomeTitulo = rowEmpresasParceirasTitulo.createCell(0);
      cellEmpresasParceirasNomeTitulo.setCellValue("EMPRESA");
      cellEmpresasParceirasNomeTitulo.setCellStyle(cellStyleTituloTabela);
      HSSFCell cellEmpresasParceirasQtdeTitulo = rowEmpresasParceirasTitulo.createCell(1);
      cellEmpresasParceirasQtdeTitulo.setCellValue("QTDE.");
      cellEmpresasParceirasQtdeTitulo.setCellStyle(cellStyleTituloTabela);

      for (int i = 0; i < detalheEmpresaParceiraList.size(); i++)
      {
         DetalheEmpresa detalhe = detalheEmpresaParceiraList.get(i);

         HSSFRow rowEmpresasParceirasConteudo = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
         HSSFCell cellEmpresasParceirasNomeConteudo = rowEmpresasParceirasConteudo.createCell(0);
         cellEmpresasParceirasNomeConteudo.setCellValue(detalhe.getNome());
         cellEmpresasParceirasNomeConteudo.setCellStyle(cellStyleConteudoTabela);
         HSSFCell cellEmpresasParceirasQtdeConteudo = rowEmpresasParceirasConteudo.createCell(1);
         cellEmpresasParceirasQtdeConteudo.setCellValue(detalhe.getQuantidadeAtendimentos());
         cellEmpresasParceirasQtdeConteudo.setCellStyle(cellStyleConteudoTabela);
      }

      rowVazia = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);

      // TABELA: Particulares
      HSSFRow rowParticularCabecalho = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellParticularCabecalho = rowParticularCabecalho.createCell(0);
      cellParticularCabecalho.setCellValue("PARTICULARES");
      cellParticularCabecalho.setCellStyle(cellStyleTitulo1C);
      sheetConsolidacao.addMergedRegion(new CellRangeAddress(sheetConsolidacao.getLastRowNum(), sheetConsolidacao.getLastRowNum(), 0, 3));
      HSSFRow rowParticularTitulo = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
      HSSFCell cellParticularNomeTitulo = rowParticularTitulo.createCell(0);
      cellParticularNomeTitulo.setCellValue("EMPRESA");
      cellParticularNomeTitulo.setCellStyle(cellStyleTituloTabela);
      HSSFCell cellParticularQtdeTitulo = rowParticularTitulo.createCell(1);
      cellParticularQtdeTitulo.setCellValue("QTDE.");
      cellParticularQtdeTitulo.setCellStyle(cellStyleTituloTabela);

      for (int i = 0; i < detalheParticularList.size(); i++)
      {
         DetalheEmpresa detalhe = detalheParticularList.get(i);

         HSSFRow rowParticularConteudo = sheetConsolidacao.createRow(sheetConsolidacao.getLastRowNum() + 1);
         HSSFCell cellParticularNomeConteudo = rowParticularConteudo.createCell(0);
         cellParticularNomeConteudo.setCellValue(detalhe.getNome());
         cellParticularNomeConteudo.setCellStyle(cellStyleConteudoTabela);
         HSSFCell cellParticularQtdeConteudo = rowParticularConteudo.createCell(1);
         cellParticularQtdeConteudo.setCellValue(detalhe.getQuantidadeAtendimentos());
         cellParticularQtdeConteudo.setCellStyle(cellStyleConteudoTabela);
      }

      sheetConsolidacao.autoSizeColumn(0);
      sheetConsolidacao.autoSizeColumn(1);
      sheetConsolidacao.autoSizeColumn(2);
      sheetConsolidacao.autoSizeColumn(3);
      sheetConsolidacao.autoSizeColumn(4);

      try
      {
         File file = new File(periodo + ".xls");
         FileOutputStream fileOut = new FileOutputStream(file);
         workbook.write(fileOut);
         fileOut.close();

         EasyOptionPane.showInfoMessageDialog(null, "Arquivo " + file.getName() + " gerado com sucesso!\nLocal: " + file.getAbsolutePath());
      }
      catch (FileNotFoundException e)
      {
         logger.error(e.getMessage(), e);
         EasyOptionPane.showErrorMessageDialog(null, e.getMessage());
      }
      catch (IOException e)
      {
         logger.error(e.getMessage(), e);
      }
   }

   /**
    * Identifica a semana em que uma data está para o período (mês) indicado.
    * 
    * @param data Data do mês.
    * @return Retorna a identificação da semana.
    */
   private String descobrirSemanaDaData(Date data)
   {
      Calendar calendar = Calendar.getInstance();
      calendar.setTime(data);
      calendar.setMinimalDaysInFirstWeek(1);

      return calendar.get(Calendar.WEEK_OF_MONTH) + "ª SEMANA";
   }

   private List<DetalheEmpresa> detalhaEmpresas(List<AtendimentoBean> atendimentoBeanList, TipoEmpresa tipoEmpresa)
   {
      List<DetalheEmpresa> detalheEmpresaList = new ArrayList<DetalheEmpresa>();
      Map<String, DetalheEmpresa> detalheEmpresaMap = new TreeMap<String, DetalheEmpresa>();

      for (AtendimentoBean bean : atendimentoBeanList)
      {
         DetalheEmpresa detalheEmpresa = new DetalheEmpresa();
         String empresa;
         switch (tipoEmpresa)
         {
            case COORDENACAO:
               empresa = bean.getCoordenacao();
               break;
            case EMPRESA_PARCEIRA:
               empresa = bean.getEmpresaParceira();
               break;
            case PARTICULAR:
               empresa = bean.getParticular();
               break;
            default:
               empresa = "";
               break;
         }

         if (!empresa.trim().equals(""))
         {
            if (detalheEmpresaMap.containsKey(empresa))
            {
               detalheEmpresa = detalheEmpresaMap.get(empresa);
               detalheEmpresa.setQuantidadeAtendimentos(detalheEmpresa.getQuantidadeAtendimentos() + 1);
            }
            else
            {
               detalheEmpresa.setNome(empresa);
               detalheEmpresa.setQuantidadeAtendimentos(1);
            }

            detalheEmpresa.setTipoEmpresa(tipoEmpresa);
            detalheEmpresaMap.put(empresa, detalheEmpresa);
         }
      }

      for (String key : detalheEmpresaMap.keySet())
      {
         detalheEmpresaList.add(detalheEmpresaMap.get(key));
      }

      Collections.sort(detalheEmpresaList);

      return detalheEmpresaList;
   }

   private List<AgendaBean> getAgendas() throws ControleAtendimentoException
   {
      if (agendaBeanList == null)
      {
         agendaBeanList = excelAgenda.obterRegistros();
      }

      return agendaBeanList;
   }

   private int getAgendas(Date data)
   {
      int ret = 0;

      try
      {
         for (AgendaBean bean : getAgendas())
         {
            if (bean.getData().equals(data))
            {
               ret = bean.getQtdeMatutino() + bean.getQtdeVespertino();
            }
         }
      }
      catch (ControleAtendimentoException e)
      {
         e.printStackTrace();
      }

      return ret;
   }

   /**
    * Obtém a maior quantidade de atendimentos em uma agenda. A agenda é derivada da data, turno e médico. Portanto, o médico que tenha
    * realizado a maior quantidade de atendimentos no seu turno em uma data específica, será o responsável pela maior agenda, ou seja, maior
    * quantidade de atendimentos.
    * 
    * @return Retorna a maior quantidade de atendimentos por um médico em um turno de um dia qualquer.
    */
   private int getMaiorAgenda()
   {
      for (String semana : semanaDataTurnoMedicoAtendimentoMap.keySet())
      {
         Map<Date, Map<String, Map<String, List<AtendimentoBean>>>> dataTurnoMedicoAtendimentoMap =
            semanaDataTurnoMedicoAtendimentoMap.get(semana);

         for (Date data : dataTurnoMedicoAtendimentoMap.keySet())
         {
            Map<String, Map<String, List<AtendimentoBean>>> turnoMedicoAtendimentoMap = dataTurnoMedicoAtendimentoMap.get(data);

            for (String turno : turnoMedicoAtendimentoMap.keySet())
            {
               Map<String, List<AtendimentoBean>> medicoAtendimentoBean = turnoMedicoAtendimentoMap.get(turno);

               for (String medico : medicoAtendimentoBean.keySet())
               {
                  List<AtendimentoBean> atendimentoList = medicoAtendimentoBean.get(medico);

                  if (atendimentoList.size() > maiorAgenda)
                  {
                     maiorAgenda = atendimentoList.size();
                  }
               }
            }
         }
      }

      return maiorAgenda;
   }

   /**
    * Obtém o nome do médico e a respectiva quantidade de atendimentos realizados, quando a quantidade é maior que 25.
    * 
    * @param medicoAtendimentosMap Mapeamento da quantidade de atendimentos por médico.
    * @return Retorna o nome do médico com a quantidade de atendimentos.
    */
   private String getMedicosComMaisDe25Atendimentos(Map<String, Integer> medicoAtendimentosMap)
   {
      StringBuffer sb = new StringBuffer();

      for (String medico : medicoAtendimentosMap.keySet())
      {
         if (medicoAtendimentosMap.get(medico) > 25)
            sb.append(medico + "=" + medicoAtendimentosMap.get(medico) + "\n");
      }

      return sb.toString();
   }

   /**
    * Obtém uma quantidade de médicos que tenham realizado mais de 25 atendimentos em um período (semana).
    * 
    * @param medicoAtendimentosMap Mapeamento da quantidade de atendimentos por médico.
    * @return Retorna a quantidade de médicos com mais de 25 atendimentos.
    */
   private int getQuantidadeMedicosComMaisDe25Atendimentos(Map<String, Integer> medicoAtendimentosMap)
   {
      int medicosComMaisDe25Atendimentos = 0;

      for (String medico : medicoAtendimentosMap.keySet())
      {
         if (medicoAtendimentosMap.get(medico) > 25)
            medicosComMaisDe25Atendimentos++;
      }

      return medicosComMaisDe25Atendimentos;
   }

   /**
    * Incrementa o número de agendas em uma semana.
    * 
    * @param semana Semana de atendimentos.
    * @param dataAtendimento Data dos atendimentos.
    */
   private void incrementaAgendasDaSemana(String semana, Date dataAtendimento)
   {
      DetalheAtendimentoInternoSemanal detalheAtendimentoInternoSemanal;

      if (detalheAtendimentoInternoMap.containsKey(semana))
      {
         detalheAtendimentoInternoSemanal = detalheAtendimentoInternoMap.get(semana);
      }
      else
      {
         detalheAtendimentoInternoSemanal = new DetalheAtendimentoInternoSemanal();
      }

      if (!detalheAtendimentoInternoSemanal.getDataAgendasContabilizadas().contains(dataAtendimento))
      {
         detalheAtendimentoInternoSemanal.setAgendas(detalheAtendimentoInternoSemanal.getAgendas() + getAgendas(dataAtendimento));
         detalheAtendimentoInternoSemanal.addDataAgendasContabilizadas(dataAtendimento);
      }

      detalheAtendimentoInternoMap.put(semana, detalheAtendimentoInternoSemanal);
   }

   private void incrementaAgendasDoMedico(String medico)
   {
      DetalheMedicoAtendimentos detalheMedicoAtendimentos;
      int total = 0;

      if (detalheAtendimentoPorMedicoMap.containsKey(medico))
         detalheMedicoAtendimentos = detalheAtendimentoPorMedicoMap.get(medico);
      else
         detalheMedicoAtendimentos = new DetalheMedicoAtendimentos();

      total = detalheMedicoAtendimentos.getQuantidadeAgendas();
      detalheMedicoAtendimentos.setQuantidadeAgendas(++total);

      detalheAtendimentoPorMedicoMap.put(medico, detalheMedicoAtendimentos);
   }

   /**
    * Incrementa o número de atendimentos realizados na semana. Todos os atendimentos da semana e atendimentos de cada médico.
    * 
    * @param semana Semana de realização dos atendimentos
    * @param medico Médico que atuou nos atendimentos
    * @param atendimentoList Lista de atendimentos realizados na semana pelo médico
    */
   private void incrementaAtendimentosDaSemana(String semana, String medico, List<AtendimentoBean> atendimentoList)
   {
      DetalheAtendimentoInternoSemanal detalheAtendimentoInterno;
      Map<String, Integer> medicoAtendimentosMap;
      Integer qtdeAtendimentosDoMedico;

      if (detalheAtendimentoInternoMap.containsKey(semana))
      {
         detalheAtendimentoInterno = detalheAtendimentoInternoMap.get(semana);
      }
      else
      {
         detalheAtendimentoInterno = new DetalheAtendimentoInternoSemanal();
      }

      if (!detalheAtendimentoInterno.getMedicoAtendimentosMap().isEmpty())
      {
         medicoAtendimentosMap = detalheAtendimentoInterno.getMedicoAtendimentosMap();
      }
      else
      {
         medicoAtendimentosMap = new TreeMap<String, Integer>();
      }

      if (medicoAtendimentosMap.containsKey(medico))
      {
         qtdeAtendimentosDoMedico = medicoAtendimentosMap.get(medico);
      }
      else
      {
         qtdeAtendimentosDoMedico = 0;
      }

      qtdeAtendimentosDoMedico += atendimentoList.size();
      medicoAtendimentosMap.put(medico, qtdeAtendimentosDoMedico);

      detalheAtendimentoInterno.setMedicoAtendimentosMap(medicoAtendimentosMap);
      detalheAtendimentoInterno.setAtendimentos(detalheAtendimentoInterno.getAtendimentos() + atendimentoList.size());

      detalheAtendimentoInternoMap.put(semana, detalheAtendimentoInterno);
   }

   /**
    * Incrementa a quantidade de atendimentos realizados por um médico em um turno qualquer.
    * 
    * @param medico Médico.
    * @param atendimentoList Lista de atendimentos do turno.
    */
   private void incrementaAtendimentosDoMedico(String medico, List<AtendimentoBean> atendimentoList)
   {
      int total = 0;
      DetalheMedicoAtendimentos detalheMedicoAtendimentos;

      if (detalheAtendimentoPorMedicoMap.containsKey(medico))
         detalheMedicoAtendimentos = detalheAtendimentoPorMedicoMap.get(medico);
      else
         detalheMedicoAtendimentos = new DetalheMedicoAtendimentos();

      total = detalheMedicoAtendimentos.getQuantidadeAtendimentos();

      for (AtendimentoBean bean : atendimentoList)
      {
         if (bean.getMedico().equals(medico))
         {
            total++;
         }
      }

      detalheMedicoAtendimentos.setQuantidadeAtendimentos(total);
      detalheAtendimentoPorMedicoMap.put(medico, detalheMedicoAtendimentos);
   }

   private void incrementaTipoDeExame(List<AtendimentoBean> atendimentoList)
   {
      for (AtendimentoBean bean : atendimentoList)
      {
         int total = 1;
         if (exameQtdeMap.containsKey(bean.getTipoDeExame()))
            total = exameQtdeMap.get(bean.getTipoDeExame()) + 1;

         exameQtdeMap.put(bean.getTipoDeExame(), total);
      }
   }

   private void load() throws ControleAtendimentoException
   {
      List<AtendimentoBean> atendimentoBeanList = excelAtendimento.obterRegistros(periodo);

      detalheCoordenacaoList = detalhaEmpresas(atendimentoBeanList, TipoEmpresa.COORDENACAO);
      detalheEmpresaParceiraList = detalhaEmpresas(atendimentoBeanList, TipoEmpresa.EMPRESA_PARCEIRA);
      detalheParticularList = detalhaEmpresas(atendimentoBeanList, TipoEmpresa.PARTICULAR);

      for (AtendimentoBean bean : atendimentoBeanList)
      {
         Date dataAtendimento = bean.getDataAtendimento();
         String turno = bean.getTurno();
         String medico = bean.getMedico();
         String semana = descobrirSemanaDaData(dataAtendimento);

         Map<Date, Map<String, Map<String, List<AtendimentoBean>>>> dataTurnoMedicoAtendimentoMap;
         if (semanaDataTurnoMedicoAtendimentoMap.containsKey(semana))
         {
            dataTurnoMedicoAtendimentoMap = semanaDataTurnoMedicoAtendimentoMap.get(semana);
         }
         else
         {
            dataTurnoMedicoAtendimentoMap = new TreeMap<Date, Map<String, Map<String, List<AtendimentoBean>>>>();
         }

         Map<String, Map<String, List<AtendimentoBean>>> turnoMedicoAtendimentoMap;
         if (dataTurnoMedicoAtendimentoMap.containsKey(dataAtendimento))
         {
            turnoMedicoAtendimentoMap = dataTurnoMedicoAtendimentoMap.get(dataAtendimento);
         }
         else
         {
            turnoMedicoAtendimentoMap = new TreeMap<String, Map<String, List<AtendimentoBean>>>();
         }

         Map<String, List<AtendimentoBean>> medicoAtendimentoMap;
         if (turnoMedicoAtendimentoMap.containsKey(turno))
         {
            medicoAtendimentoMap = turnoMedicoAtendimentoMap.get(turno);
         }
         else
         {
            medicoAtendimentoMap = new TreeMap<String, List<AtendimentoBean>>();
         }

         List<AtendimentoBean> atendimentoList;
         if (medicoAtendimentoMap.containsKey(medico))
         {
            atendimentoList = medicoAtendimentoMap.get(medico);
         }
         else
         {
            atendimentoList = new ArrayList<AtendimentoBean>();
         }

         atendimentoList.add(bean);
         medicoAtendimentoMap.put(medico, atendimentoList);
         turnoMedicoAtendimentoMap.put(turno, medicoAtendimentoMap);
         dataTurnoMedicoAtendimentoMap.put(dataAtendimento, turnoMedicoAtendimentoMap);
         semanaDataTurnoMedicoAtendimentoMap.put(semana, dataTurnoMedicoAtendimentoMap);
      }

      totalizaDiasUteis(periodo);

      for (String semana : semanaDataTurnoMedicoAtendimentoMap.keySet())
      {
         Map<Date, Map<String, Map<String, List<AtendimentoBean>>>> dataTurnoMedicoAtendimentoMap =
            semanaDataTurnoMedicoAtendimentoMap.get(semana);

         for (Date dataAtendimento : dataTurnoMedicoAtendimentoMap.keySet())
         {
            Map<String, Map<String, List<AtendimentoBean>>> turnoMedicoAtendimentoMap = dataTurnoMedicoAtendimentoMap.get(dataAtendimento);

            for (String turno : turnoMedicoAtendimentoMap.keySet())
            {
               Map<String, List<AtendimentoBean>> medicoAtendimentoMap = turnoMedicoAtendimentoMap.get(turno);

               for (String medico : medicoAtendimentoMap.keySet())
               {
                  List<AtendimentoBean> atendimentoList = medicoAtendimentoMap.get(medico);

                  incrementaAtendimentosDaSemana(semana, medico, atendimentoList);
                  incrementaAgendasDaSemana(semana, dataAtendimento);
                  incrementaAtendimentosDoMedico(medico, atendimentoList);
                  incrementaAgendasDoMedico(medico);
                  incrementaTipoDeExame(atendimentoList);
               }
            }
         }
      }
   }

   private void totalizaDiasUteis(String periodo)
   {
      DateFormat mesAno = new SimpleDateFormat("MMM-yyyy");
      Calendar calendar = Calendar.getInstance();
      try
      {
         Date data = mesAno.parse(periodo);
         calendar.setTime(data);
         int month = calendar.get(Calendar.MONTH);

         if (calendar.get(Calendar.DAY_OF_MONTH) != calendar.getActualMinimum(Calendar.DAY_OF_MONTH))
         {
            calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
         }

         for (AgendaBean bean : agendaBeanList)
         {
            if (bean.getData().equals(calendar.getTime()) && calendar.get(Calendar.MONTH) == month)
            {
               if (bean.getQtdeMatutino() > 0 || bean.getQtdeVespertino() > 0)
                  diasUteis++;

               calendar.add(Calendar.DAY_OF_MONTH, 1);
            }
         }
      }
      catch (ParseException e)
      {
         e.printStackTrace();
      }
   }
}
